#include <DBChecker.h>
#include <Driver.h>
#include <FLock.h>

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>

#include <iostream>
#include <cstring>

#include <init_drivers.hpp>

int usage(){
	std::cout << "usage: cexpert_s <connection str>" << std::endl;
	return 0;
}

void daemonize(void) {
	int fd;
	switch (fork()) {
	case 0:
		break;
	case -1:
		// Error
		fprintf(stderr, "Error demonizing (fork)! %d - %s\n", errno, strerror(errno));
		exit(0);
		break;
	default:
		_exit(0);
	}

	if (setsid() < 0) {
		fprintf(stderr, "Error demonizing (setsid)! %d - %s\n", errno, strerror(errno));
		exit(0);
	}
	switch (fork()) {
	case 0:
		break;
	case -1:
		// Error
		fprintf(stderr, "Error demonizing (fork2)! %d - %s\n", errno, strerror(errno));
		exit(0);
		break;
	default:
		_exit(0);
	}

	fd = open("/dev/null", O_RDONLY);
	if (fd != 0) {
		dup2(fd, 0);
		close(fd);
	}
	fd = open("/dev/null", O_WRONLY);
	if (fd != 1) {
		dup2(fd, 1);
		close(fd);
	}
	fd = open("/dev/null", O_WRONLY);
	if (fd != 2) {
		dup2(fd, 2);
		close(fd);
	}

}

void* checker_thread(void* arg){
    CExpert::DBChecker* self = reinterpret_cast<CExpert::DBChecker*>(arg);
    const CExpert::DBChecker::conn_params& cp = self->get_cp();

    while (!self->is_stopped()){
        try{
            if (!CExpert::get_driver(cp.driver)(cp)){
                self->fail();
            } else{
                self->ok();
            }
        }
        catch (const std::exception& ex){
            std::cerr << ex.what() << std::endl;
            self->stop();
        }
        sleep(1);
    }
    return NULL;
}

int main(int argc, char** argv){
	if (argc != 2)
		return usage();

	daemonize();
	CExpert::FLock lock(argv[1]);
	CExpert::DBChecker checker(argv[1], true);
	std::string safe_args = CExpert::DBChecker::connstr2filename(argv[1]);
	//XXX what is strlen(safe_args) > strlen(argv[1])? CORE DUMP.
	strncpy(argv[1], safe_args.c_str(), strlen(argv[1]));

	checker.start(&checker_thread);

	std::cout << "cexpert_s started with connection str: " << argv[1] << std::endl;
    checker.join();
    return 0;
}
